home *** CD-ROM | disk | FTP | other *** search
/ Amiga Plus 2000 #5 / Amiga Plus CD - 2000 - No. 5.iso / Tools / Dev / FPSE_src / malloc.c < prev    next >
C/C++ Source or Header  |  2000-01-01  |  2KB  |  120 lines

  1. /*
  2.      malloc for first-fit way by BERO
  3.      don't dupulicate free()
  4. */
  5.  
  6. #include "fpse.h"
  7.  
  8. enum {FREE,USED};
  9.  
  10. typedef struct _CHUNK {
  11.      struct _CHUNK *next,*prev;
  12.      UINT32  size;
  13.      int  type;
  14. } CHUNK;
  15.  
  16. static CHUNK *heapbase;
  17.  
  18. #define   ALIGN     4
  19.  
  20. void bios_InitHeap(void *block, UINT32 size)
  21. {
  22.      heapbase = block;
  23.      heapbase->next = NULL;
  24.      heapbase->prev = NULL;
  25.      heapbase->size = size;
  26.      heapbase->type = FREE;
  27. }
  28.  
  29. #define   MINSIZE   (sizeof(CHUNK)+8)
  30.  
  31. static void split_chunk(CHUNK *p, UINT32 size2)
  32. {
  33.      /* | p             |
  34.         | p   |  free   | */
  35.  
  36.      if (p->size-size2>=MINSIZE) {
  37.           CHUNK *next = (CHUNK*)((char*)p + size2);
  38.           next->prev = p;
  39.           next->next = p->next;
  40.           next->size = p->size-size2;
  41.           next->type = FREE;
  42.           p->size = size2;
  43.           p->next = next;
  44.      }
  45. }
  46.  
  47. static void merge_chunk(CHUNK *p)
  48. {
  49.      /* | p   |  free   |
  50.         | p             | */
  51.  
  52.      if (p->next && p->next->type==FREE) {
  53.           p->size += p->next->size;
  54.           p->next  = p->next->next;
  55.      }
  56. }
  57.  
  58. void *bios_malloc(UINT32 size)
  59. {
  60.      CHUNK *p;
  61.      size_t size2 = (size+sizeof(CHUNK)+ALIGN-1)&~(ALIGN-1);
  62.  
  63.      for(p=heapbase;p && (p->type!=FREE || p->size<size2);p=p->next) ;
  64.      if (p==NULL) return NULL;
  65.      p->type = USED;
  66.      split_chunk(p,size2);
  67.  
  68.      return p+1;
  69. }
  70.  
  71. void *bios_calloc(UINT32 size, UINT32 n)
  72. {
  73.      size_t sizen = size*n;
  74.      void *buf = bios_malloc(sizen);
  75.      if (buf) {
  76.           memset(buf,0,sizen);
  77.      }
  78.      return buf;
  79. }
  80.  
  81. void bios_free(void *ptr)
  82. {
  83.      CHUNK *p = (CHUNK*)ptr-1;
  84.  
  85.      p->type = FREE;
  86.  
  87.      merge_chunk(p);
  88.      /* |free|  p  | ?? |
  89.         | prev     | ?? | */
  90.      if (p->prev && p->prev->type==FREE) {
  91.           p->prev->size += p->size;
  92.           p->prev->next  = p->next;
  93.      }
  94. }
  95.  
  96. void *bios_realloc(void *ptr, UINT32 size)
  97. {
  98.      size_t size2;
  99.      CHUNK *p;
  100.  
  101.      if (ptr==NULL) return malloc(size);
  102.      if (size==0) free(ptr);
  103.  
  104.      size2 = (size+sizeof(CHUNK)+ALIGN-1)&~(ALIGN-1);
  105.      p = (CHUNK*)ptr-1;
  106.  
  107.      if (p->size>=size2
  108.      || (p->next && p->next->type==FREE && p->size+p->next->size>=size2)) {
  109.           merge_chunk(p);
  110.           split_chunk(p,size2);
  111.           return ptr;
  112.      } else {
  113.           void *newp = malloc(size);
  114.           if (newp) {
  115.                memcpy(newp,ptr,size);
  116.                free(ptr);
  117.           }
  118.           return newp;
  119.      }
  120. }